package ooad.nextgen.domain;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import ooad.nextgen.gof.factory.PricingStrategyFactory;
import ooad.nextgen.gof.strategy.ISalePricingStrategy;
import ooad.nextgen.gof.observer.PropertyListener;

public class Sale {
	private List<SalesLineItem> lineItems = new ArrayList<SalesLineItem>() ;
	private Date date = new Date();
	private boolean isComplete = false;
	private Payment payment;
	private Money total = new Money();
	private Money preDiscountTotal = new Money(); //折扣前总金额
	private ISalePricingStrategy pricingStrategy;
        List<PropertyListener> pls = new ArrayList<PropertyListener>();
	public Sale(){
            pricingStrategy = PricingStrategyFactory.getInstance().getSalePricingStrategy();
        
        }

	/**
	 * 计算总金额
	 * @return
	 */
	public  Money getTotal() {
		Money subtotal=null;
		for (SalesLineItem lineItem: lineItems) {
			subtotal = lineItem.getSubTotal();
			total.add(subtotal);
		}
                total = pricingStrategy.getTotal(this);
		return total;
	}
	

	public void becomeComplete() {
		this.isComplete = true;		
	}
	public void makeLineItem(ProductDescription desc, int quantity) {
		SalesLineItem lineItem = new SalesLineItem(desc,quantity);
		lineItems.add(lineItem);
		Money newTotal  = this.preDiscountTotal.add(lineItem.getSubTotal());
		this.setTotal(newTotal);
	}
        public void setTotal(Money newTotal){
		this.preDiscountTotal = newTotal;
		 this.publishPropertyEvent("sale.total", newTotal.getAmount());
	}

	public void makePayment(Money cashTendered) {
		if(isComplete){
		payment = new Payment(cashTendered);
		}
	}
        //发布订阅模式
	public void addPropertyListener(PropertyListener pl){
		pls.add(pl);
	}
	public void publishPropertyEvent(String name,Object value){
		for(PropertyListener pl:pls){
			pl.onPropertyEvent(this, name, value);
		}
	}
        
        public Money getDiscountTotal(){
		return total;
	}
	public Date getDate() {
		return date;
	}
	public List<SalesLineItem> getLineItems() {
		return lineItems;
	}

	public Money getPreDiscountTotal(){
		return preDiscountTotal;
	}
        public Money getBalance(){
		return payment.getAmount().minus(total);	
	}
}
